package com.cardcaptorsakura.service.memory;

import com.cardcaptorsakura.model.entity.Memory;
import com.cardcaptorsakura.model.entity.UserPreference;
import com.cardcaptorsakura.repository.MemoryRepository;
import com.cardcaptorsakura.repository.UserPreferenceRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * 记忆存储服务
 * 提供记忆的存储、检索、管理等核心功能
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MemoryStorageService {

    private final MemoryRepository memoryRepository;
    private final UserPreferenceRepository userPreferenceRepository;
    private final VectorSearchService vectorSearchService;
    private final MemoryAnalysisService memoryAnalysisService;

    /**
     * 创建新记忆
     */
    @Transactional
    public Memory createMemory(Memory memory) {
        try {
            // 设置默认值
            if (memory.getCreatedAt() == null) {
                memory.setCreatedAt(LocalDateTime.now());
            }
            if (memory.getUpdatedAt() == null) {
                memory.setUpdatedAt(LocalDateTime.now());
            }
            if (memory.getImportance() == null) {
                memory.setImportance(50);
            }
            if (memory.getAccessCount() == null) {
                memory.setAccessCount(0);
            }
            if (memory.getConfidence() == null) {
                memory.setConfidence(1.0);
            }
            if (memory.getVersion() == null) {
                memory.setVersion(1);
            }
            if (memory.getDeleted() == null) {
                memory.setDeleted(false);
            }

            // 生成向量嵌入
            if (memory.getRawText() != null && !memory.getRawText().isEmpty()) {
                generateEmbeddingAsync(memory);
            }

            // 分析记忆内容
            analyzeMemoryContentAsync(memory);

            // 保存记忆
            Memory savedMemory = memoryRepository.save(memory);
            log.info("Created memory: {} for user: {}", savedMemory.getId(), savedMemory.getUserId());

            return savedMemory;
        } catch (Exception e) {
            log.error("Error creating memory for user: {}", memory.getUserId(), e);
            throw new RuntimeException("Failed to create memory", e);
        }
    }

    /**
     * 批量创建记忆
     */
    @Transactional
    public List<Memory> createMemories(List<Memory> memories) {
        try {
            List<Memory> processedMemories = memories.stream()
                .map(memory -> {
                    // 设置默认值
                    if (memory.getCreatedAt() == null) {
                        memory.setCreatedAt(LocalDateTime.now());
                    }
                    if (memory.getUpdatedAt() == null) {
                        memory.setUpdatedAt(LocalDateTime.now());
                    }
                    if (memory.getImportance() == null) {
                        memory.setImportance(50);
                    }
                    if (memory.getAccessCount() == null) {
                        memory.setAccessCount(0);
                    }
                    if (memory.getConfidence() == null) {
                        memory.setConfidence(1.0);
                    }
                    if (memory.getVersion() == null) {
                        memory.setVersion(1);
                    }
                    if (memory.getDeleted() == null) {
                        memory.setDeleted(false);
                    }
                    return memory;
                })
                .collect(Collectors.toList());

            List<Memory> savedMemories = memoryRepository.saveAll(processedMemories);

            // 异步处理向量嵌入和内容分析
            savedMemories.forEach(memory -> {
                if (memory.getRawText() != null && !memory.getRawText().isEmpty()) {
                    generateEmbeddingAsync(memory);
                }
                analyzeMemoryContentAsync(memory);
            });

            log.info("Created {} memories", savedMemories.size());
            return savedMemories;
        } catch (Exception e) {
            log.error("Error creating batch memories", e);
            throw new RuntimeException("Failed to create memories", e);
        }
    }

    /**
     * 更新记忆
     */
    @Transactional
    public Memory updateMemory(Memory memory) {
        try {
            Optional<Memory> existingMemoryOpt = memoryRepository.findById(memory.getId());
            if (existingMemoryOpt.isEmpty()) {
                throw new RuntimeException("Memory not found: " + memory.getId());
            }

            Memory existingMemory = existingMemoryOpt.get();
            
            // 更新字段
            if (memory.getTitle() != null) {
                existingMemory.setTitle(memory.getTitle());
            }
            if (memory.getContent() != null) {
                existingMemory.setContent(memory.getContent());
            }
            if (memory.getRawText() != null) {
                existingMemory.setRawText(memory.getRawText());
                // 重新生成向量嵌入
                generateEmbeddingAsync(existingMemory);
            }
            if (memory.getImportance() != null) {
                existingMemory.setImportance(memory.getImportance());
            }
            if (memory.getEmotionTags() != null) {
                existingMemory.setEmotionTags(memory.getEmotionTags());
            }
            if (memory.getTopicTags() != null) {
                existingMemory.setTopicTags(memory.getTopicTags());
            }
            if (memory.getKeywords() != null) {
                existingMemory.setKeywords(memory.getKeywords());
            }
            if (memory.getEntities() != null) {
                existingMemory.setEntities(memory.getEntities());
            }
            if (memory.getContext() != null) {
                existingMemory.setContext(memory.getContext());
            }
            if (memory.getExpiresAt() != null) {
                existingMemory.setExpiresAt(memory.getExpiresAt());
            }
            if (memory.getRelatedMemoryIds() != null) {
                existingMemory.setRelatedMemoryIds(memory.getRelatedMemoryIds());
            }
            if (memory.getMetadata() != null) {
                existingMemory.setMetadata(memory.getMetadata());
            }

            existingMemory.setUpdatedAt(LocalDateTime.now());
            existingMemory.setVersion(existingMemory.getVersion() + 1);

            Memory savedMemory = memoryRepository.save(existingMemory);
            log.info("Updated memory: {} for user: {}", savedMemory.getId(), savedMemory.getUserId());

            return savedMemory;
        } catch (Exception e) {
            log.error("Error updating memory: {}", memory.getId(), e);
            throw new RuntimeException("Failed to update memory", e);
        }
    }

    /**
     * 根据ID获取记忆
     */
    public Optional<Memory> getMemoryById(String id) {
        try {
            Optional<Memory> memoryOpt = memoryRepository.findByIdAndDeletedFalse(id);
            if (memoryOpt.isPresent()) {
                Memory memory = memoryOpt.get();
                // 增加访问次数
                memory.incrementAccessCount();
                memoryRepository.save(memory);
            }
            return memoryOpt;
        } catch (Exception e) {
            log.error("Error getting memory by id: {}", id, e);
            return Optional.empty();
        }
    }

    /**
     * 根据用户ID获取记忆列表
     */
    public List<Memory> getMemoriesByUserId(String userId) {
        try {
            return memoryRepository.findByUserIdAndDeletedFalse(userId);
        } catch (Exception e) {
            log.error("Error getting memories for user: {}", userId, e);
            return Collections.emptyList();
        }
    }

    /**
     * 根据用户ID分页获取记忆列表
     */
    public Page<Memory> getMemoriesByUserId(String userId, int page, int size, String sortBy, String sortDirection) {
        try {
            Sort.Direction direction = "desc".equalsIgnoreCase(sortDirection) ? 
                Sort.Direction.DESC : Sort.Direction.ASC;
            Pageable pageable = PageRequest.of(page, size, Sort.by(direction, sortBy));
            return memoryRepository.findByUserIdAndDeletedFalse(userId, pageable);
        } catch (Exception e) {
            log.error("Error getting paginated memories for user: {}", userId, e);
            return Page.empty();
        }
    }

    /**
     * 根据用户ID和记忆类型获取记忆列表
     */
    public List<Memory> getMemoriesByUserIdAndType(String userId, Memory.MemoryType memoryType) {
        try {
            return memoryRepository.findByUserIdAndMemoryTypeAndDeletedFalse(userId, memoryType);
        } catch (Exception e) {
            log.error("Error getting memories by type for user: {}, type: {}", userId, memoryType, e);
            return Collections.emptyList();
        }
    }

    /**
     * 根据会话ID获取记忆列表
     */
    public List<Memory> getMemoriesByConversationId(String conversationId) {
        try {
            return memoryRepository.findByConversationIdAndDeletedFalseOrderByCreatedAtAsc(conversationId);
        } catch (Exception e) {
            log.error("Error getting memories for conversation: {}", conversationId, e);
            return Collections.emptyList();
        }
    }

    /**
     * 搜索记忆
     */
    public List<Memory> searchMemories(String userId, String query, int limit) {
        try {
            // 首先尝试向量搜索
            List<Memory> vectorResults = vectorSearchService.searchSimilarMemories(userId, query, limit);
            if (!vectorResults.isEmpty()) {
                return vectorResults;
            }

            // 如果向量搜索没有结果，使用文本搜索
            Pageable pageable = PageRequest.of(0, limit);
            Page<Memory> textResults = memoryRepository.searchMemoriesByText(userId, query, pageable);
            if (!textResults.isEmpty()) {
                return textResults.getContent();
            }

            // 最后使用模糊搜索
            Page<Memory> fuzzyResults = memoryRepository.findByUserIdAndContentContaining(userId, query, pageable);
            return fuzzyResults.getContent();
        } catch (Exception e) {
            log.error("Error searching memories for user: {}, query: {}", userId, query, e);
            return Collections.emptyList();
        }
    }

    /**
     * 获取相似记忆
     */
    public List<Memory> getSimilarMemories(String memoryId, int limit) {
        try {
            Optional<Memory> memoryOpt = getMemoryById(memoryId);
            if (memoryOpt.isEmpty()) {
                return Collections.emptyList();
            }

            Memory memory = memoryOpt.get();
            return vectorSearchService.findSimilarMemories(memory, limit);
        } catch (Exception e) {
            log.error("Error getting similar memories for: {}", memoryId, e);
            return Collections.emptyList();
        }
    }

    /**
     * 获取用户的重要记忆
     */
    public List<Memory> getImportantMemories(String userId, int minImportance, int limit) {
        try {
            Pageable pageable = PageRequest.of(0, limit, Sort.by(Sort.Direction.DESC, "importance"));
            Page<Memory> results = memoryRepository.findByUserIdAndImportanceRange(userId, minImportance, 100, pageable);
            return results.getContent();
        } catch (Exception e) {
            log.error("Error getting important memories for user: {}", userId, e);
            return Collections.emptyList();
        }
    }

    /**
     * 获取用户的最近记忆
     */
    public List<Memory> getRecentMemories(String userId, int limit) {
        try {
            Pageable pageable = PageRequest.of(0, limit, Sort.by(Sort.Direction.DESC, "createdAt"));
            Page<Memory> results = memoryRepository.findByUserIdAndDeletedFalse(userId, pageable);
            return results.getContent();
        } catch (Exception e) {
            log.error("Error getting recent memories for user: {}", userId, e);
            return Collections.emptyList();
        }
    }

    /**
     * 获取用户的活跃记忆
     */
    public List<Memory> getActiveMemories(String userId, int days) {
        try {
            LocalDateTime since = LocalDateTime.now().minusDays(days);
            return memoryRepository.findActiveMemoriesByUserId(userId, since);
        } catch (Exception e) {
            log.error("Error getting active memories for user: {}", userId, e);
            return Collections.emptyList();
        }
    }

    /**
     * 根据标签获取记忆
     */
    public List<Memory> getMemoriesByTags(String userId, List<String> emotionTags, List<String> topicTags) {
        try {
            List<Memory> results = new ArrayList<>();
            
            if (emotionTags != null && !emotionTags.isEmpty()) {
                results.addAll(memoryRepository.findByUserIdAndEmotionTags(userId, emotionTags));
            }
            
            if (topicTags != null && !topicTags.isEmpty()) {
                List<Memory> topicResults = memoryRepository.findByUserIdAndTopicTags(userId, topicTags);
                // 合并结果，避免重复
                for (Memory memory : topicResults) {
                    if (!results.stream().anyMatch(m -> m.getId().equals(memory.getId()))) {
                        results.add(memory);
                    }
                }
            }
            
            return results;
        } catch (Exception e) {
            log.error("Error getting memories by tags for user: {}", userId, e);
            return Collections.emptyList();
        }
    }

    /**
     * 根据关键词获取记忆
     */
    public List<Memory> getMemoriesByKeywords(String userId, List<String> keywords) {
        try {
            return memoryRepository.findByUserIdAndKeywords(userId, keywords);
        } catch (Exception e) {
            log.error("Error getting memories by keywords for user: {}", userId, e);
            return Collections.emptyList();
        }
    }

    /**
     * 软删除记忆
     */
    @Transactional
    public boolean deleteMemory(String id) {
        try {
            Optional<Memory> memoryOpt = memoryRepository.findById(id);
            if (memoryOpt.isEmpty()) {
                return false;
            }

            Memory memory = memoryOpt.get();
            memory.softDelete();
            memoryRepository.save(memory);
            
            log.info("Soft deleted memory: {}", id);
            return true;
        } catch (Exception e) {
            log.error("Error deleting memory: {}", id, e);
            return false;
        }
    }

    /**
     * 批量软删除记忆
     */
    @Transactional
    public int deleteMemories(List<String> ids) {
        try {
            List<Memory> memories = memoryRepository.findByIdIn(ids);
            int deletedCount = 0;
            
            for (Memory memory : memories) {
                if (!memory.getDeleted()) {
                    memory.softDelete();
                    deletedCount++;
                }
            }
            
            memoryRepository.saveAll(memories);
            log.info("Soft deleted {} memories", deletedCount);
            return deletedCount;
        } catch (Exception e) {
            log.error("Error batch deleting memories", e);
            return 0;
        }
    }

    /**
     * 恢复已删除的记忆
     */
    @Transactional
    public boolean restoreMemory(String id) {
        try {
            Optional<Memory> memoryOpt = memoryRepository.findById(id);
            if (memoryOpt.isEmpty()) {
                return false;
            }

            Memory memory = memoryOpt.get();
            memory.restore();
            memoryRepository.save(memory);
            
            log.info("Restored memory: {}", id);
            return true;
        } catch (Exception e) {
            log.error("Error restoring memory: {}", id, e);
            return false;
        }
    }

    /**
     * 永久删除记忆
     */
    @Transactional
    public boolean permanentlyDeleteMemory(String id) {
        try {
            memoryRepository.deleteById(id);
            log.info("Permanently deleted memory: {}", id);
            return true;
        } catch (Exception e) {
            log.error("Error permanently deleting memory: {}", id, e);
            return false;
        }
    }

    /**
     * 清理过期记忆
     */
    @Transactional
    public int cleanupExpiredMemories() {
        try {
            List<Memory> expiredMemories = memoryRepository.findExpiredMemories(LocalDateTime.now());
            int cleanedCount = 0;
            
            for (Memory memory : expiredMemories) {
                memory.softDelete();
                cleanedCount++;
            }
            
            memoryRepository.saveAll(expiredMemories);
            log.info("Cleaned up {} expired memories", cleanedCount);
            return cleanedCount;
        } catch (Exception e) {
            log.error("Error cleaning up expired memories", e);
            return 0;
        }
    }

    /**
     * 清理长时间未访问的低重要性记忆
     */
    @Transactional
    public int cleanupInactiveMemories(int maxImportance, int inactiveDays) {
        try {
            LocalDateTime threshold = LocalDateTime.now().minusDays(inactiveDays);
            List<Memory> inactiveMemories = memoryRepository.findLowImportanceInactiveMemories(maxImportance, threshold);
            int cleanedCount = 0;
            
            for (Memory memory : inactiveMemories) {
                memory.softDelete();
                cleanedCount++;
            }
            
            memoryRepository.saveAll(inactiveMemories);
            log.info("Cleaned up {} inactive memories", cleanedCount);
            return cleanedCount;
        } catch (Exception e) {
            log.error("Error cleaning up inactive memories", e);
            return 0;
        }
    }

    /**
     * 永久清理已删除的记忆
     */
    @Transactional
    public int permanentlyCleanupDeletedMemories(int retentionDays) {
        try {
            LocalDateTime threshold = LocalDateTime.now().minusDays(retentionDays);
            List<Memory> deletedMemories = memoryRepository.findDeletedMemoriesForCleanup(threshold);
            
            for (Memory memory : deletedMemories) {
                memoryRepository.delete(memory);
            }
            
            log.info("Permanently cleaned up {} deleted memories", deletedMemories.size());
            return deletedMemories.size();
        } catch (Exception e) {
            log.error("Error permanently cleaning up deleted memories", e);
            return 0;
        }
    }

    /**
     * 获取记忆统计信息
     */
    public MemoryStatistics getMemoryStatistics(String userId) {
        try {
            long totalCount = memoryRepository.countByUserIdAndDeletedFalse(userId);
            Optional<Integer> totalAccess = memoryRepository.getTotalAccessCountByUserId(userId);
            Optional<Double> avgImportance = memoryRepository.getAverageImportanceByUserId(userId);
            
            List<MemoryRepository.MemoryTypeCount> typeDistribution = 
                memoryRepository.getMemoryTypeDistributionByUserId(userId);
            List<MemoryRepository.TagCount> topEmotionTags = 
                memoryRepository.getTopEmotionTagsByUserId(userId);
            List<MemoryRepository.TagCount> topTopicTags = 
                memoryRepository.getTopTopicTagsByUserId(userId);
            List<MemoryRepository.TagCount> topKeywords = 
                memoryRepository.getTopKeywordsByUserId(userId);
            
            return MemoryStatistics.builder()
                .userId(userId)
                .totalMemories(totalCount)
                .totalAccess(totalAccess.orElse(0))
                .averageImportance(avgImportance.orElse(0.0))
                .typeDistribution(typeDistribution)
                .topEmotionTags(topEmotionTags)
                .topTopicTags(topTopicTags)
                .topKeywords(topKeywords)
                .generatedAt(LocalDateTime.now())
                .build();
        } catch (Exception e) {
            log.error("Error getting memory statistics for user: {}", userId, e);
            return null;
        }
    }

    /**
     * 异步生成向量嵌入
     */
    @Async
    public CompletableFuture<Void> generateEmbeddingAsync(Memory memory) {
        try {
            List<Double> embedding = vectorSearchService.generateEmbedding(memory.getRawText());
            memory.updateEmbedding(embedding);
            memoryRepository.save(memory);
            log.debug("Generated embedding for memory: {}", memory.getId());
        } catch (Exception e) {
            log.error("Error generating embedding for memory: {}", memory.getId(), e);
        }
        return CompletableFuture.completedFuture(null);
    }

    /**
     * 异步分析记忆内容
     */
    @Async
    public CompletableFuture<Void> analyzeMemoryContentAsync(Memory memory) {
        try {
            memoryAnalysisService.analyzeMemoryContent(memory);
            memoryRepository.save(memory);
            log.debug("Analyzed content for memory: {}", memory.getId());
        } catch (Exception e) {
            log.error("Error analyzing content for memory: {}", memory.getId(), e);
        }
        return CompletableFuture.completedFuture(null);
    }

    /**
     * 记忆统计信息
     */
    @lombok.Data
    @lombok.Builder
    @lombok.NoArgsConstructor
    @lombok.AllArgsConstructor
    public static class MemoryStatistics {
        private String userId;
        private long totalMemories;
        private int totalAccess;
        private double averageImportance;
        private List<MemoryRepository.MemoryTypeCount> typeDistribution;
        private List<MemoryRepository.TagCount> topEmotionTags;
        private List<MemoryRepository.TagCount> topTopicTags;
        private List<MemoryRepository.TagCount> topKeywords;
        private LocalDateTime generatedAt;
    }
}